package com.jcompressor;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;

import com.jcompressor.entities.Project;
import com.jcompressor.exceptions.JcompressorException;
import com.jcompressor.preferences.ConfigKeys;
import com.jcompressor.preferences.ConfigurationHandler;

public class Controller {
	
	public static void main(final String[] args) {
		try {
			final Jcompressor jc = new Jcompressor();
			final CommandLine cmd = new PosixParser().parse(Controller.getOptions(), args);
			if (cmd.getOptions().length == 0) {
				final StringBuffer config = new StringBuffer(ConfigKeys.JCOMPRESSOR_HOME);
				config.append(ConfigKeys.FILE_SEPARATOR);
				config.append("jcompressor-config.xml");
				
				jc.setConfigurations(ConfigurationHandler.parseJcompressorConfiguration(config.toString()));
				jc.loadProjects();
				
				Controller.getUserInput(jc);
			}
			else {
				if (cmd.hasOption(ConfigKeys.PROJECT)) {
					jc.getStream().info("Loading projects: ");
					jc.getStream().empty();
					
					final String projectParam = cmd.getOptionValue(ConfigKeys.PROJECT);
					for (final String configuration : StringUtils.split(projectParam, ',')) {
						jc.loadProject(configuration);
					}
					
					Controller.getUserInput(jc);
				}
				else if (cmd.hasOption(ConfigKeys.HELP)) {
					new HelpFormatter().printHelp("jcompressor", Controller.getOptions());
				}
				else if (cmd.hasOption(ConfigKeys.VERSION)) {
					jc.getStream().exit();
				}
				else {
					final List<String> options = new ArrayList<String>();
					if (cmd.hasOption(ConfigKeys.YUI_OPTIONS)) {
						final String[] yuiOptions = StringUtils.split(cmd.getOptionValue(ConfigKeys.YUI_OPTIONS), ' ');
						for (final String option : yuiOptions) {
							options.add(option);
						}
					}
					
					if (cmd.hasOption(ConfigKeys.JS)) {
						jc.start(cmd.getOptionValues(ConfigKeys.JS), ConfigKeys.JS, options);
					}
					
					if (cmd.hasOption(ConfigKeys.CSS)) {
						jc.start(cmd.getOptionValues(ConfigKeys.CSS), ConfigKeys.CSS, options);
					}
				}
			}
		}
		catch (Exception e) {
			throw new JcompressorException(e);
		}
	}
	
	public static void getUserInput(final Jcompressor jc) {
		try {
			final int projectCount = jc.getProjects().size();
			if (projectCount > 0) {
				jc.listProjects();
				jc.getStream().info((projectCount + 1) + ". All projects");
				jc.getStream().info((projectCount + 2) + ". Exit");
				jc.getStream().empty();
				jc.getStream().print("Select a project: ");
				
				final String line = jc.getStream().getReader().readLine();
				if (NumberUtils.isNumber(line)) {
					final int projectId = NumberUtils.toInt(line);
					if ((projectId > 0) && (projectId <= projectCount)) {
						jc.getStream().flush();
						jc.initProject(jc.getProjects().get(projectId - 1));
						return;
					}
					else if (projectId == (projectCount + 1)) {
						jc.getStream().flush();
						
						for (final Project project : jc.getProjects()) {
							jc.initProject(project);
						}
						
						return;
					}
					else if (projectId == (projectCount + 2)) {
						Controller.exit(jc);
					}
				}
				
				jc.getStream().empty();
				jc.getStream().info("Invalid selection. Please try again.");
				jc.getStream().empty();
				
				Controller.getUserInput(jc);
			}
			else {
				Controller.exit(jc);
			}
		}
		catch (Exception e) {
			throw new JcompressorException(e);
		}
	}
	
	private static Options getOptions() {
		final Option project = new Option(ConfigKeys.PROJECT, "project", true, "path to the configuration file of the project that will be compressed");
		project.setArgName("path");
		
		final Option js = new Option(ConfigKeys.JS, true, "path to the javascript file(s) that will be compressed");
		js.setArgs(2);
		js.setArgName("input output");
		js.setValueSeparator(' ');
		
		final Option css = new Option(ConfigKeys.CSS, true, "path to the stylesheet file(s) that will be compressed");
		css.setArgs(2);
		css.setArgName("input output");
		css.setValueSeparator(' ');
		
		final Option yuiOptions = new Option(ConfigKeys.YUI_OPTIONS, true, "yui compressor options");
		yuiOptions.setArgName("options");
		
		final Options options = new Options();
		options.addOption(ConfigKeys.HELP, "help", false, "show help options");
		options.addOption(ConfigKeys.VERSION, "version", false, "print version and quit");
		options.addOption(project);
		options.addOption(js);
		options.addOption(css);
		options.addOption(yuiOptions);
		return options;
	}
	
	private static void exit(final Jcompressor jc) {
		jc.getStream().info("Exiting jcompressor...");
		jc.getStream().info("Goodbye.");
		jc.getStream().exit();
	}
	
}